package com.ww.juc.completable.future.multi.task;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 多任务组合处理
 * 
 * thenCombine：会将两个任务的执行结果作为所提供函数的参数，且该方法有返回值；
 * thenAcceptBoth：同样将两个任务的执行结果作为方法入参，但是无返回值；
 * runAfterBoth：没有入参，也没有返回值。
 * 注意两个任务中只要有一个执行异常，则将该异常信息作为指定任务的执行结果。
 * 
 * @author wanggw
 * 2024年2月4日 下午6:18:49
 */
public class MultiTaskCombineDemo {

	public static void main(String[] args) throws InterruptedException, ExecutionException {
//		testThenAcceptBoth();
		
		testRunAfterBoth();
	}
	
	
	@SuppressWarnings("unused")
	private static void testRunAfterBoth() throws InterruptedException, ExecutionException {
		long startTime = System.currentTimeMillis();
		
		CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
			System.out.println(Thread.currentThread() + "任务1，活跃起来了...");
			try {
				System.out.println(Thread.currentThread() + "任务1开始睡眠...");
				TimeUnit.SECONDS.sleep(3L);
				System.out.println(Thread.currentThread() + "任务1结束睡眠了.");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return 1;
		});
		
		CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(() -> {
			System.out.println(Thread.currentThread() + "任务2，动起来...");
			try {
				System.out.println(Thread.currentThread() + "任务2开始睡眠...");
				TimeUnit.SECONDS.sleep(5L);
				System.out.println(Thread.currentThread() + "任务2结束睡眠了.");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return 10;
		});
		
		CompletableFuture<Void> cf3 = cf1.runAfterBoth(cf2, () -> {
			System.out.println("有事没事大家来凑个热闹，不用带东西来");
		});
		
		System.out.println(cf3.get());
		
		System.out.println("总耗时：" + (System.currentTimeMillis() - startTime) / 1000 + "秒");
		
//		打印结果
//		Thread[ForkJoinPool.commonPool-worker-9,5,main]任务1，活跃起来了...
//		Thread[ForkJoinPool.commonPool-worker-2,5,main]任务2，动起来...
//		有事没事大家来凑个热闹，不用带东西来
//		null
	}
	
	
	/**
	 * thenAcceptBoth：同样将两个任务的执行结果作为方法入参，但是无返回值；
	 * @throws ExecutionException 
	 * @throws InterruptedException 
	 */
	@SuppressWarnings("unused")
	private static void testThenAcceptBoth() throws InterruptedException, ExecutionException {
		CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
			System.out.println(Thread.currentThread() + "任务1已经开始干活了...");
			return 1;
		});
		
		CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(() -> {
			System.out.println(Thread.currentThread() + "任务2起来去工作了...");
			return 100;
		});
		
		CompletableFuture<Void> cf3 = cf1.thenAcceptBoth(cf2, (a, b) -> {
			System.out.println(Thread.currentThread() + "乐迪合体，超级加速……");
			System.out.println(a + b);
		});
		System.out.println("最后合并结果：" + cf3.get());
		
//		打印结果
//		Thread[ForkJoinPool.commonPool-worker-9,5,main]任务1已经开始干活了...
//		Thread[ForkJoinPool.commonPool-worker-9,5,main]任务2起来去工作了...
//		Thread[main,5,main]乐迪合体，超级加速……
//		101
//		最后合并结果：null
	}
	
	
	@SuppressWarnings("unused")
	private static void testThenCombine() throws InterruptedException, ExecutionException {
		CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
			System.out.println(Thread.currentThread() + "任务1已经开始干活了...");
			return 1;
		});
		
		CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(() -> {
			System.out.println(Thread.currentThread() + "任务2已经开始干活了...");
			return 2;
		});
		
		CompletableFuture<Integer> cf3 = cf1.thenCombine(cf2, (a, b) -> {
			System.out.println(Thread.currentThread() + "合并任务执行了，哈哈哈");
			return a + b;
		});
		
		System.out.println("结果3：" + cf3.get());
	}
}
